﻿using DapperExtensions.Mapper;
using System;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.SQLite;
using System.Data.SqlClient;
using System.Data.OracleClient;
using Dapper;
using DapperExtensions;
using DapperExtensions.Sql;
using MySql.Data.MySqlClient;

namespace System.Data
{
    public class OracleDbSession:DbSession {
        #region 初始化必须
        /// <summary>
        ///初始化，需要传入连接字符串
        /// </summary>
        /// <param name="conStr">连接字符串</param>
        /// <returns></returns>
        public OracleDbSession(string conStr) : base(conStr)
        {
            //DapperExtensions默认是用SqlServer的标记，这边使用Oracle的特殊语法标记，需要在初始化时给予指定。
            //DapperExtensions是静态的，全局只能支持一种数据库 
            DapperExtensions.DapperExtensions.SqlDialect = new DapperExtensions.Sql.OracleDialect();
            DbType = DatabaseType.Oracle;
        }

        /// <summary>
        /// 创建连接对象。子类需要重写，根据自己的数据库类型实例化自己的数据库连接对象(支持IDbConnection接口)。
        /// Dapper可以在所有Ado.net Providers下工作，包括sqlite, sqlce, firebird, oracle, MySQL, PostgreSQL and SQL Server。
        /// </summary>
        /// <returns></returns>
        protected override IDbConnection CreateConnection()
        {
            IDbConnection connection = new OracleConnection(ConnectionString);//Oracle.ManagedDataAccess.Client
            return connection;
        }
        #endregion

        #region oracle版的ExecuteDataSet
        /// <summary>
        /// oracle版。执行sql语句，并返回DataSet。为了简化写法，支持oracle一条sql有多条语句，用;隔开。
        /// (oracle一条sql不能执行多个语句，需要特殊处理，现在方案：一个连接多个DataReader)
        /// </summary>
        /// <param name="sql">sql如有多条语句，则用;隔开</param>
        /// <param name="param">匿名对象的参数，可以简单写，比如 new {Name="user1"} 即可，会统一处理参数和参数的size</param>
        public override DataSet ExecuteDataSet(string sql, dynamic param = null, int? cmdTimeout = DEFAULTTIMEOUT, IDbTransaction tran = null, CommandType? cmdType = null)
        {
            sql = CheckSql(sql);
            var sqls = sql.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            var conn = CreateConnectionAndOpen();
            try
            {
                DataSet dataSet = new DataSet();
                foreach (var singleSql in sqls)
                {
                    if (string.IsNullOrWhiteSpace(singleSql)) continue;
                    //经测试，Odp.Net中OracleDataAdapter.Fill第一次调用有性能问题，第二次就正常。而SqlServer的SqlDataAdapter.Fill无此问题
                    //这边用Dapper的ExecuteReader，即解决OracleDataAdapter.Fill的问题，又统一了函数参数写法，不用使用OracleParameter。
                    using (var reader = conn.ExecuteReader(singleSql, (object)param, tran, cmdTimeout, cmdType))
                    {
                        var dataTable = DataReaderToDataTable(reader);
                        dataSet.Tables.Add(dataTable);
                    }
                }
                return dataSet;
            }
            finally
            {
                conn.Close();
            }
        }
        #endregion

        

        #region 数据结构
        public override bool AddTableFieldInfo(string tableName, string fieldName, string info)
        {
            throw new NotImplementedException();
        }

        public override bool CleanAllTableData<T>()
        {
            throw new NotImplementedException();
        }

        public override bool CreateTable(Type type)
        {
            throw new NotImplementedException();
        }

        public override bool CreateTable<T>(bool cover = true)
        {
            throw new NotImplementedException();
        }

        public override bool DropTable<T>()
        {
            throw new NotImplementedException();
        }

        public override List<DataBaseModel> GetDataBases()
        {
            throw new NotImplementedException();
        }

        public override List<TableColumn> GetTableColumns(string tableName = "")
        {
            throw new NotImplementedException();
        }

        public override List<TableModel> GetTables()
        {
            throw new NotImplementedException();
        }
        public override bool TestDataGenerate(string tableName, int count = 20)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}
